package com.lty.bbapp.netty;

import java.util.List;

import org.apache.log4j.Logger;

import com.lty.bbapp.entity.EBoardPack;
import com.lty.bbapp.entity.InOutStationPack;
import com.lty.bbapp.util.Coordinate;
import com.lty.bbapp.util.MyUtils;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

/***
 * 
* <p>Title: MyNettyDecoder</p>
* <p>Description: 自定义netty解码器</p>
* <p>Company: lty</p>
* @author liuhao
* @date 2016年12月13日 下午6:44:07
* version 1.0
 */
public class MyNettyDecoder extends ByteToMessageDecoder { 
	
	private static final Logger logger = Logger.getLogger(MyNettyDecoder.class);  
	  
    @Override  
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception 
    {  
//    	ByteBuf buf =  in.copy();
//    	byte[] allData = new byte[buf.readableBytes()];
//    	buf.readBytes(allData);
		
//    	logger.info("newMaxRead:"+newMaxRead+" ,newContent:"+MyUtils.bytes2hex03(b));
    	
//    	in.readBytes(oldMaxRead);
    	
    	// 如果没有接收完Header部分（14字节），直接退出该方法  
        if(in.readableBytes() > 14-3) 
        {  
            // 标记开始位置  
            in.markReaderIndex();  
            
            String headFlag = "*";
            String facInfo = "FH";
            
            /*//对数据包头标志进行判断  
            if(!headFlag.equals("*")){
            	//找不到包头,丢弃多余字节
                if(in.readableBytes() > 0)
                    in.skipBytes(in.readableBytes());
                return;
            }
            
            byte[] facInfoBytes = new byte[2];
            in.readBytes(facInfoBytes);
            String facInfo = new String(facInfoBytes);
            
            */
            int versionByte = in.readByte();
            String version = "V".concat(String.valueOf(versionByte)).concat(".0");
            
            byte reservedHead = in.readByte();
            
            byte[] equiIdBytes = new byte[5];
            in.readBytes(equiIdBytes);
			String equiId = MyUtils.convertHexString(equiIdBytes);
			
//			if(equiId.equals("0470000003"))
//			{
//				logger.info("1111111111："+MyUtils.bytes2hex03(allData));
//			}
//			
//			if(equiId.equals("0E7E01010E"))
//			{
//				logger.info("2222222222："+MyUtils.bytes2hex03(allData));
//			}
//			
//			if(equiId.equals("0E7E010121"))
//			{
//				logger.info("3333333333:"+MyUtils.bytes2hex03(allData));
//			}
//			if(equiId.equals("0466010122"))
//			{
//				logger.info("4444444444:"+MyUtils.bytes2hex03(allData));
//			}
//			
//			
//			
//			if(equiId.equals("0E01040503"))
//			{
//				logger.info("55555555555:"+MyUtils.bytes2hex03(allData));
//			}
//			if(equiId.equals("0E01040504"))
//			{
//				logger.info("6666666666:"+MyUtils.bytes2hex03(allData));
//			}
//			if(equiId.equals("0E01040505"))
//			{
//				logger.info("77777777777:"+MyUtils.bytes2hex03(allData));
//			}
//			if(equiId.equals("0E01040506"))
//			{
//				logger.info("888888888:"+MyUtils.bytes2hex03(allData));
//			}
//			if(equiId.equals("0E01040507"))
//			{
//				logger.info("999999999:"+MyUtils.bytes2hex03(allData));
//			}
//			
//			if(equiId.equals("0E7E010107"))
//			{
//				logger.info("*************:"+MyUtils.bytes2hex03(allData));
//			}
            
			byte commandFlag = in.readByte();
			String commandFlagStr = MyUtils.convertHexString(new byte[]{commandFlag});
			
			byte[] bodyLengthBytes = new byte[2];
			in.readBytes(bodyLengthBytes);
			int bodyLength = MyUtils.bytes2int(bodyLengthBytes);
			
			byte headCheckSum = in.readByte();
			
			//***************************包头结束，包体开始****************************//*
			//如果是GPS和进出站包
        	if(commandFlagStr.equals("12") || commandFlagStr.equals("18") || commandFlagStr.equals("19"))
        	{
                //如果body的长度少于23  
                if(in.readableBytes() < 23) 
                {  
            		//出错的数据
            		byte[] errorByte = new byte[in.readableBytes()];
            		in.readBytes(errorByte);
            		
            		/*logger.error("body没有接收完整，body体的数据为："+MyUtils.bytes2hex03(errorByte)+"\r\n"+
            		"此次的完整包为："+MyUtils.bytes2hex03(allData));*/
                	
                } 
                else {  
        			if(commandFlagStr.equals("12")){//gps数据包
//仅做测试用        				decodeFormalGps(headFlag,facInfo,version,reservedHead,equiId,commandFlag,bodyLength,headCheckSum,ctx,in,out,allData);
        				decodeFormalGps(headFlag,facInfo,version,reservedHead,equiId,commandFlag,bodyLength,headCheckSum,ctx,in,out);
        			}
        			
        			else if(commandFlagStr.equals("18") || commandFlagStr.equals("19")){//进出站数据包
//仅做测试用          			decodeFormalInOut(commandFlagStr,headFlag,facInfo,version,reservedHead,equiId,commandFlag,bodyLength,headCheckSum,ctx,in,out,allData);
        				decodeFormalInOut(commandFlagStr,headFlag,facInfo,version,reservedHead,equiId,commandFlag,bodyLength,headCheckSum,ctx,in,out);
    				}
        			
        			//如果到此时包还没有读完，为了不影响下一次解包，读完此次剩余数据
        			if(in.readableBytes() > 0)
        			{
        				//出错的数据
        				byte[] errorByte = new byte[in.readableBytes()];
        				in.readBytes(errorByte);
        				
        				/*logger.error("读到最后包还没有读完，最后的数据为："+MyUtils.bytes2hex03(errorByte)+"\r\n"+
    		    				"此次包的完整包为："+MyUtils.bytes2hex03(allData));*/
        				
        			}
                } 
        	}
        	
        	//其他包直接跳过，不处理
        	else 
        	{
				in.skipBytes(in.readableBytes());
			}
 
        }  
    	
        //包的长度不满足包头的长度，直接跳过这个包
        else
        {
        	/*String string = MyUtils.bytes2hex03(allData);
        	
        	String end = string.substring(string.length()-2, string.length());*/
        	
        	/*if(!"23".equals(end))
        	{
        		logger.error("包的长度不满足包头的长度\r\n"+
        				"此次包的完整包为："+string);
        	}*/
        	in.skipBytes(in.readableBytes());
        }
    }  
    
    //gps数据包
//仅做测试用      private void decodeFormalGps(String headFlag,String facInfo,String version,byte reservedHead,String equiId,byte commandFlag,int bodyLength,byte headCheckSum,ChannelHandlerContext ctx, ByteBuf in, List<Object> out,byte[] error) throws Exception{
    private void decodeFormalGps(String headFlag,String facInfo,String version,byte reservedHead,String equiId,byte commandFlag,int bodyLength,byte headCheckSum,ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception{
    	byte respFlag = in.readByte();//应答标志
    	
    	//组帧时间  如：0x10 0x50 0x10表示为10点50分10秒
		byte[] frameTimeBytes = new byte[3];
		in.readBytes(frameTimeBytes);
		String frameTime = MyUtils.convertHexString(frameTimeBytes);
		
		String t1 = frameTime.substring(0, 2);
		String t2 = frameTime.substring(2, 4);
		String t3 = frameTime.substring(4, 6);
		frameTime = t1.concat(":").concat(t2).concat(":").concat(t3);
		
		//纬度
		byte[] latBytes = new byte[4];
		in.readBytes(latBytes);
		
		//16进制数据中最高位为1表示北纬，为0表示南纬 ；
		//所以flag为1表示北纬  ，为-1表示南纬
		int latFlag = ((latBytes[0] & 0x80) == 128?1:-1);
		
		latBytes[0] = (byte) (latBytes[0] & 0x7F);
		int latitudeNum = MyUtils.bytes2int(latBytes);
		
		int latDu = latitudeNum/1000000;
		double latFen = (latitudeNum%1000000)/10000.0;
		
		//度=度+分/60
		double latDuReal = latDu + (latFen/60.0);
		
		Coordinate latCoordinate = new Coordinate(latDuReal);
		
		double latitude = latCoordinate.getDoubleValue()*latFlag;
		
		byte[] lonBytes = new byte[4];
		in.readBytes(lonBytes);
		
		//flag为1表示东经  ，为-1表示西经
		int lonFlag = ((lonBytes[0] & 0x80) == 128?1:-1);
		
		lonBytes[0] = (byte) (lonBytes[0] & 0x7F);
		int longtitudeNum = MyUtils.bytes2int(lonBytes);
		
		int lonDu = longtitudeNum/1000000;
		double lonFen = (longtitudeNum%1000000)/10000.0;
		//度=度+分/60
		double lonDuReal = lonDu + (lonFen/60.0);
		
		Coordinate lonCoordinate = new Coordinate(lonDuReal);
		double longtitude = lonCoordinate.getDoubleValue()*lonFlag;
		
		byte[] velocityBytes = new byte[2];
		in.readBytes(velocityBytes);
		int velocity = MyUtils.bytes2int(velocityBytes);
		
		byte[] angleBytes = new byte[2];
		in.readBytes(angleBytes);
		int angle = MyUtils.bytes2int(angleBytes);
		
		byte[] reservedBodyBytes = new byte[4];
		in.readBytes(reservedBodyBytes);
		int reservedBody = MyUtils.bytes2int(reservedBodyBytes);
		
		byte[] bodyCheckSumBytes = new byte[2];
		in.readBytes(bodyCheckSumBytes);
		int bodyCheckSum = MyUtils.bytes2int(bodyCheckSumBytes);
		
		String endFlag = new String(new byte[]{in.readByte()});
		
		//不是以#结束
		if(!"#".equals(endFlag))
		{
			/*logger.error("此次包不是以#结束\r\n"+
			        "此次的完整包为："+MyUtils.bytes2hex03(error));*/
			return;
		}
          
		EBoardPack pack = new EBoardPack(headFlag, facInfo, version, reservedHead, equiId, commandFlag, bodyLength, headCheckSum, respFlag, frameTime, latitude, longtitude, velocity, angle, reservedBody, bodyCheckSum, endFlag); 
      
		out.add(pack); // 解析出一条消息  
    }
    
    //gps数据包
//仅做测试用      private void decodeFormalInOut(String commandType,String headFlag,String facInfo,String version,byte reservedHead,String equiId,byte commandFlag,int bodyLength,byte headCheckSum,ChannelHandlerContext ctx, ByteBuf in, List<Object> out,byte[] error) throws Exception{
    	private void decodeFormalInOut(String commandType,String headFlag,String facInfo,String version,byte reservedHead,String equiId,byte commandFlag,int bodyLength,byte headCheckSum,ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception{
    	int type = 0;
		
		if(commandType.equals("19")){
			type = 1;
		}
		
		byte respFlag = in.readByte();
		
		byte[] frameTimeBytes = new byte[3];
		in.readBytes(frameTimeBytes);
		String frameTime = MyUtils.convertHexString(frameTimeBytes);
		
		String t1 = frameTime.substring(0, 2);
		String t2 = frameTime.substring(2, 4);
		String t3 = frameTime.substring(4, 6);
		frameTime = t1.concat(":").concat(t2).concat(":").concat(t3);
		
		//纬度
		byte[] latBytes = new byte[4];
		in.readBytes(latBytes);
				
		//16进制数据中最高位为1表示北纬，为0表示南纬 ；
		//所以flag为1表示北纬  ，为-1表示南纬
		int latFlag = ((latBytes[0] & 0x80) == 128?1:-1);
				
		latBytes[0] = (byte) (latBytes[0] & 0x7F);
		int latitudeNum = MyUtils.bytes2int(latBytes);
				
		int latDu = latitudeNum/1000000;
		double latFen = (latitudeNum%1000000)/10000.0;
				
		//度=度+分/60
		double latDuReal = latDu + (latFen/60.0);
				
		Coordinate latCoordinate = new Coordinate(latDuReal);
				
		double latitude = latCoordinate.getDoubleValue()*latFlag;
				
		byte[] lonBytes = new byte[4];
		in.readBytes(lonBytes);
				
		//flag为1表示东经  ，为-1表示西经
		int lonFlag = ((lonBytes[0] & 0x80) == 128?1:-1);
				
		lonBytes[0] = (byte) (lonBytes[0] & 0x7F);
		int longtitudeNum = MyUtils.bytes2int(lonBytes);
				
		int lonDu = longtitudeNum/1000000;
		double lonFen = (longtitudeNum%1000000)/10000.0;
		//度=度+分/60
		double lonDuReal = lonDu + (lonFen/60.0);
				
		Coordinate lonCoordinate = new Coordinate(lonDuReal);
		double longtitude = lonCoordinate.getDoubleValue()*lonFlag;
		
		byte[] velocityBytes = new byte[2];
		in.readBytes(velocityBytes);
		int velocity = MyUtils.bytes2int(velocityBytes);
		
		byte[] angleBytes = new byte[2];
		in.readBytes(angleBytes);
		int angle = MyUtils.bytes2int(angleBytes);
		
		byte direction = in.readByte();
		
		byte stationNo = in.readByte();
		
		byte boardCount = in.readByte();
		
		byte downCount = in.readByte();
		
		byte[] bodyCheckSumBytes = new byte[2];
		in.readBytes(bodyCheckSumBytes);
		int bodyCheckSum = MyUtils.bytes2int(bodyCheckSumBytes);
		
		String endFlag = new String(new byte[]{in.readByte()});
		
		//不是以#结束
		if(!"#".equals(endFlag))
		{
			/*logger.error("此次包不是以#结束\r\n"+
	        		"此次的完整包为："+MyUtils.bytes2hex03(error));*/
			return;
		}
		
		InOutStationPack pack = new InOutStationPack(type, headFlag, facInfo, version, reservedHead, equiId, commandFlag, bodyLength, headCheckSum, respFlag, frameTime, latitude, longtitude, velocity, angle, direction, stationNo, boardCount, downCount, bodyCheckSum, endFlag);
		
		out.add(pack);
    }
    
}  
